/** 
 * 节点对象扩展
 * Author      : donggang
 * Create Time : 2016.8.9
 */

/** 
 * 创建Sprite类型的节点组件 
 * @param resPath(string)        资源地址（资源必须已加载到内存中）
 * @param spriteFrameKey(string) 精灵帧关键字
 */
cc.Node.createSprite = function(resPath, spriteFrameKey = null) {
    var node   = new cc.Node();
    var sprite = node.addComponent(cc.Sprite);
    if (spriteFrameKey == null) {
        var sf = cc.loader.getResByType(resPath,cc.SpriteFrame);
        if (sf)
            sprite.spriteFrame = cc.loader.getResByType(resPath,cc.SpriteFrame);
        else
            cc.error("路径为【{0}】的精灵资源不在内存中，请先加载".format(resPath));
    }
    else { 
        var sa = cc.loader.getResByType(resPath,cc.SpriteFrame);
        if (sa)
            sprite.spriteFrame = cc.loader.getResByType(resPath,cc.SpriteAtlas).getSpriteFrame(spriteFrameKey);
        else
            cc.error("路径为【{0}】的图集资源不在内存中，请先加载".format(resPath));
    }
        
    return node;
}

/** 
 * 复制给定的对象并绑定脚本组件
 * @param resPath(string)      预制资源地址
 * @param scriptPath(string)   脚本资源地址
 */
cc.Node.createPrefab = function(resPath, scriptPath){
    var prefab = cc.loader.getRes(resPath);
    if (prefab == null) {
        cc.error("路径为【{0}】的预制资源不在内存中，请先加载".format(resPath));
        return null;
    }

    var result = cc.instantiate(prefab);
    if (scriptPath && result.getComponent(scriptPath) == null)
        result.addComponent(require(scriptPath));
        
    return result;
}

/** 创建一个全屏模糊层蒙板 */
cc.Node.createBlock = function(alpha = 100){
    var node = new cc.Node("block");
    var ctx = node.addComponent(cc.Graphics);
    ctx.rect(
        -cc.director.getWinSize().width / 2, 
        -cc.director.getWinSize().height / 2, 
        cc.director.getWinSize().width, 
        cc.director.getWinSize().height);
    ctx.fillColor = cc.color(0, 0, 0, alpha);
    ctx.fill();
    return node;
}

/** 创建一个全屏阻挡触摸事件的节点 */
cc.Node.createBlockEventNode = function(){
    var node = new cc.Node("null_node");
    node.setContentSize(cc.director.getWinSize().width, cc.director.getWinSize().height);
    return node;
}

/** 所有触摸事件停止冒泡开启 */
cc.Node.touchStopPropagationOpen = function(node){
    node.on(cc.Node.EventType.TOUCH_START , cc.Node._stopPropagation);
    node.on(cc.Node.EventType.TOUCH_MOVE  , cc.Node._stopPropagation);
    node.on(cc.Node.EventType.TOUCH_END   , cc.Node._stopPropagation);
    node.on(cc.Node.EventType.TOUCH_CANCEL, cc.Node._stopPropagation);

    node.on(cc.Node.EventType.MOUSE_ENTER, cc.Node._stopPropagation);
    node.on(cc.Node.EventType.MOUSE_LEAVE, cc.Node._stopPropagation);
},

/** 所有触摸事件停止冒泡关闭 */
cc.Node.touchStopPropagationClose = function(node){
    node.off(cc.Node.EventType.TOUCH_START , cc.Node._stopPropagation);
    node.off(cc.Node.EventType.TOUCH_MOVE  , cc.Node._stopPropagation);
    node.off(cc.Node.EventType.TOUCH_END   , cc.Node._stopPropagation);
    node.off(cc.Node.EventType.TOUCH_CANCEL, cc.Node._stopPropagation);

    node.off(cc.Node.EventType.MOUSE_ENTER, cc.Node._stopPropagation);
    node.off(cc.Node.EventType.MOUSE_LEAVE, cc.Node._stopPropagation);
}

cc.Node._stopPropagation = function(event){
    event.stopPropagation();
}

//--------------------------------------------------------------------------------------------------------------

/**
 * 播放节点上 Spine 动画
 * @param node(cc.Node)        目标节点
 * @param clipName(string)     动画剪辑名
 * @param loop(boolen)         是否循环播放
 * @param callback(function)   动画事件回调
 */
cc.Node.prototype.playSpineAnimation = function(clipName, loop = false){
    var skeleton = this.getComponent(sp.Skeleton);
    if (node){
        skeleton.setAnimation(0, clipName, loop ? 1 : 0);
    }
    else {
        cc.error("当前节点上不存在 Spine 动画组件");
    }
    return skeleton;
}

/** 
 * 触发所有组件的指定方法
 * @param funName(string)    方法名
 * @param params(Array)      数组
 */
cc.Node.prototype.applyComponentsFunction = function(funName, params){
    var components = this._components;
    for (var i = 0; i < components.length; i++) {
        var component = components[i];
        var func      = component[funName];
        if (func) func.call(component, params);
    }
}

/** 
 * 节点上添加一个动画组件
 * @param resPath(string)      动画资源地址 
 */
cc.Node.prototype.addAnimationClip = function(resPath){
    var animClip = cc.loader.getResByType(resPath, cc.AnimationClip);
    if (animClip == null){
        cc.error("路径为【{0}】的动画资源不在内存中，请先加载".format(resPath));
        return null;
    }

    var anim = this.getComponent(cc.Animation);
    if (anim == null){
        anim = this.addComponent(cc.Animation);
    }
    anim.addClip(animClip);
    
    return anim;
}

/** 初始化资源管理环境 */
cc.Node.prototype._resManagerinit = function(){
    if (this._reference == null){
        this._reference = game.scene.__getReference();      // 引擎计数管理器
        this._resources = {};                               // 当前节点使用的资源集合
    }
}

/** 加载单个资源（使用方式和 cocos 自代同名 API 一样）*/
cc.Node.prototype.loadRes = function(url, type, completeCallback) {
    if (!completeCallback && type && !cc.isChildClassOf(type, cc.RawAsset)) {
        completeCallback = type;
        type             = null;
    }

    this._resManagerinit();
    this._reference.loadRes(url, type, completeCallback, this._resources);
}

/** 加载一个文件夹多个资源（使用方式和 cocos 自代同名 API 一样）*/
cc.Node.prototype.loadResAll = function(url, type, completeCallback) {
    if (!completeCallback && type && !cc.isChildClassOf(type, cc.RawAsset)) {
        completeCallback = type;
        type             = null;
    }

    this._resManagerinit();
    this._reference.loadResAll(url, type, completeCallback, this._resources);
}

/**
 * 加载多个资源
 * @param urls(Array)                   资源地址数组
 * @param completeCallback(function)    加载完成回调
 */
cc.Node.prototype.loadResByUrls = function(urls, completeCallback) {
    this._resManagerinit();
    this._reference.loadResByUrls(urls, completeCallback, this._resources);
}

/** 释放节点对象和引擎的资源内存 */
cc.Node.prototype.dispose = function(){ 
    if (this._reference) this._reference.destroy(this._resources);

    for (var i = 0; i < this.childrenCount; i++){
        var childNode = this.children[i]
        childNode.dispose();
    }

    this.onDestroy();
    this.destroy();
},

/** 释放节点事件 */
cc.Node.prototype.onDestroy = function(){

}